#include <sekai/UnisynIndex.h>
#include <sekai/VoiceSampler.h>
#include <sndfile.h>
#include <assert.h>

int g_samplerate = 0;

float interp_linear(float *x, float *y, int nx, float ref) {
  int i;
  for (i = 0; i < nx - 1; i++) {
    if (ref >= x[i] && ref <= x[i + 1]) {
      float x1 = x[i];
      float x2 = x[i + 1];
      float tmp = (ref - x1) / (x2 - x1);
      return y[i] * (1 - tmp) + y[i + 1] * tmp;
    }
  }
  fprintf(stderr, "INTERP_LINEAR: out of range\n");
  return NAN;
}

// new ;
class TestSynth : public VoiceSampler {
 public:
  TestSynth() : VoiceSampler(8192) {
    _index = new UnisynIndex();
    std::string dir = "/home/isengaara/Hacking/Audio/VoiceSynth/FESTIVAL/festival-czech-voices/voice-czech-krb/";
    _index->readFromFile(dir+"dic/krbdiph.est");
    _info[0] = _index->getPho("d-o");
    _info[1] = _index->getPho("r-e");
    _info[2] = _index->getPho("m-i");
    for(int i=0;i<3;i++)
    {
       std::string ogg = dir+"ogg/"+_info[i].basename+".ogg";
       SF_INFO info;
       _sf[i] = sf_open(ogg.c_str(), SFM_READ, &info);
       g_samplerate = info.samplerate;
    }
    
    _impulseResponse = new float[2048];
  }

 protected:
  virtual bool addOnePulse() {

    float currentTime = inputPositionSamples() / g_samplerate;
    int index = (int)currentTime;
    if (index == 3) return false;
    // get impulse response

    float otoTime = currentTime;
    while (otoTime > 1.0) otoTime -= 1.0;
    
    

    PhoInfo info = _info[index];
    
    assert(info.alignment.size()==3);
    float diph_start = info.alignment[0];
    float diph_middle = info.alignment[1];
    float diph_end = info.alignment[2];
    
    float x[3] = {0, diph_middle - diph_start, 1.0};
    float y[3] = {diph_start, diph_middle, diph_end};
    float index_time = interp_linear(x, y, 3, otoTime);
    
    // SynthesisMBR fft_size=2048 frame_period=5.000000
    float frame_period = 5.0;
    int fft_size = 2048;
    
    int frame_index = index_time * 1000 / frame_period;
    int frame_offset = frame_index * fft_size;
    

    sf_seek(_sf[index],frame_offset,SEEK_SET);
    sf_read_float(_sf[index],_impulseResponse,fft_size);

    float f0[3] = {261.63, 293.67, 329.63};
    float output_f0 = f0[index];
    float period = g_samplerate * 1.0f / output_f0;

    VoiceSampler::hanningWindow(_impulseResponse, fft_size);
    ola(_impulseResponse, fft_size, period);

    return true;
    
  }

 private:
  UnisynIndex* _index;
  PhoInfo _info[3];
  SNDFILE* _sf[3];
  float *_impulseResponse;
};

int main() {
  TestSynth *synth = new TestSynth();

  SF_INFO info = {0};
  info.samplerate = g_samplerate;
  info.channels = 1;
  info.format = SF_FORMAT_WAV | SF_FORMAT_PCM_16;
  SNDFILE *sf = sf_open("/tmp/test_unisyn.wav", SFM_WRITE, &info);

  while (1) {
    const int size = 1024;
    int fill = size * 4;

    float buffer_out[size];
    if (synth->readData(buffer_out, size, fill) == false) break;
    sf_write_float(sf, buffer_out, size);
  }

  sf_close(sf);
}
